package com.sc.nft.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.sc.nft.dao.ApplicationRequirementDao;
import com.sc.nft.entity.ApplicationRequirement;
import com.sc.nft.entity.UserInfo;
import com.sc.nft.entity.dto.ApplicationRequirementAddDTO;
import com.sc.nft.entity.dto.ApplicationRequirementUpdateDTO;
import com.sc.nft.entity.vo.*;
import com.sc.nft.pool.UserPool;
import com.sc.nft.service.ApplicationRequirementService;
import com.sc.nft.factory.ApplicationRequirementFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * (ApplicationRequirement)表服务实现类
 *
 * @author wwc
 * @since 2023-07-18 16:27:30
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class ApplicationRequirementServiceImpl implements ApplicationRequirementService {

    private final ApplicationRequirementDao applicationRequirementDao;

    private final ApplicationRequirementFactory applicationRequirementFactory;

    @Override
    public void add(List<ApplicationRequirementAddDTO> applicationRequirementAddDTO) {
        List<ApplicationRequirement> applicationRequirements = BeanUtil.copyToList(applicationRequirementAddDTO, ApplicationRequirement.class);
        applicationRequirements.forEach(applicationRequirement -> {
            // 根据serveType和type判定是否有存在重复的数据
            // 如果有,则不插入,如果没有,则插入
            Boolean exist = applicationRequirementDao.selectBean(applicationRequirement);
            if (exist) {
                return;
            }
            applicationRequirementDao.save(applicationRequirement);
        });
    }

    @Override
    public void updates(List<ApplicationRequirementUpdateDTO> applicationRequirementAddDTO) {
        applicationRequirementAddDTO.forEach(applicationRequirementUpdateDTO -> {
            ApplicationRequirement applicationRequirement = BeanUtil.copyProperties(applicationRequirementUpdateDTO, ApplicationRequirement.class);
            applicationRequirement.updateById();
        });
    }

    @Override
    public List<ApplicationRequirementAdminExotheciumVO> selectList(Integer serveType) {
        List<ApplicationRequirementAdminExotheciumVO>list=new ArrayList<>();
        List<ApplicationRequirementSelectListVO> applicationRequirementSelectLists = applicationRequirementDao.selectList(serveType);
        applicationRequirementSelectLists.stream().collect(Collectors.groupingBy(ApplicationRequirementSelectListVO::getTaskGroup)).forEach((k,v)->{
            ApplicationRequirementAdminExotheciumVO applicationRequirementAdminExotheciumVO=new ApplicationRequirementAdminExotheciumVO();
            applicationRequirementAdminExotheciumVO.setApplicationRequirementSelectListVO(v);
            list.add(applicationRequirementAdminExotheciumVO);
        });
        return list;
    }

    @Override
    public WebApplicationRequirementVO webApplicationRequirementVo(Integer type) {
        // 获取类型对应的数据结果集
        List<WebApplicationRequirementWhereVO> result = new ArrayList<>();
        // 根据type获取对应的数据
        List<ApplicationRequirement> applicationRequirements = applicationRequirementDao.selectListByType(type);
        Map<Integer, List<ApplicationRequirement>> taskGroupMap = applicationRequirements.stream().collect(Collectors.groupingBy(ApplicationRequirement::getTaskGroup));
        // 先根据taskGroup字段进行分组,这是每个任务组的分组.在用groupId进行分组,这是每个条件的分组进行处理
        taskGroupMap.forEach((k, v) -> {
            // 在根据groupId进行分组,分组的数据是每个申请条件的组合
            Map<Integer, List<ApplicationRequirement>> groupedByGroupId = v.stream()
                    .collect(Collectors.groupingBy(ApplicationRequirement::getGroupId));
            // 分组后的数据获取对应用户的数据组合好.
            // 这个是and的条件,必须满足
            List<ApplicationRequirementFactoryVO> andList = new ArrayList<>();
            // 这个是多组or的条件容器用来装orList
            List<List<ApplicationRequirementFactoryVO>>multiLevelList = new ArrayList<>();
            WebApplicationRequirementWhereVO webApplicationRequirementWhereVO=new WebApplicationRequirementWhereVO();
            groupedByGroupId.forEach((k1, v1) -> {
                // 这个是装or的条件
                List<ApplicationRequirementFactoryVO> orList = new ArrayList<>();
                v1.forEach(applicationRequirement -> {
                    ApplicationRequirementFactoryVO applicationRequirementFactoryVO = applicationRequirementFactory.getApplicationRequirementFactoryService(applicationRequirement.getType().getCode())
                            .applicationRequirement(UserPool.getUser(), applicationRequirement, type);
                    if ("AND".equals(applicationRequirement.getCompoundMode())) {
                        andList.add(applicationRequirementFactoryVO);
                    } else {
                        orList.add(applicationRequirementFactoryVO);
                    }
                });
                if (CollUtil.isNotEmpty(orList)) {
                    multiLevelList.add(orList);
                }
            });
            // 一个完整的申请条件,写入result中
           webApplicationRequirementWhereVO.setOrList(multiLevelList);
           webApplicationRequirementWhereVO.setAndList(andList);
           webApplicationRequirementWhereVO.setSatisfy(webApplicationRequirementWhereVO.whetherMeetTheRequirement());
           result.add(webApplicationRequirementWhereVO);
        });
        WebApplicationRequirementVO webApplicationRequirementVO = new WebApplicationRequirementVO();
        webApplicationRequirementVO.setResult(result);
        return webApplicationRequirementVO;
    }
    @Override
    public WebApplicationRequirementVO webApplicationRequirementUserVO(UserInfo userInfo, Integer type) {
        // 获取类型对应的数据结果集
        List<WebApplicationRequirementWhereVO> result = new ArrayList<>();
        // 根据type获取对应的数据
        List<ApplicationRequirement> applicationRequirements = applicationRequirementDao.selectListByType(type);
        Map<Integer, List<ApplicationRequirement>> taskGroupMap = applicationRequirements.stream().collect(Collectors.groupingBy(ApplicationRequirement::getTaskGroup));
        // 先根据taskGroup字段进行分组,这是每个任务组的分组.在用groupId进行分组,这是每个条件的分组进行处理
        taskGroupMap.forEach((k, v) -> {
            // 在根据groupId进行分组,分组的数据是每个申请条件的组合
            Map<Integer, List<ApplicationRequirement>> groupedByGroupId = v.stream()
                    .collect(Collectors.groupingBy(ApplicationRequirement::getGroupId));
            // 分组后的数据获取对应用户的数据组合好.
            // 这个是and的条件,必须满足
            List<ApplicationRequirementFactoryVO> andList = new ArrayList<>();
            // 这个是多组or的条件容器用来装orList
            List<List<ApplicationRequirementFactoryVO>>multiLevelList = new ArrayList<>();
            WebApplicationRequirementWhereVO webApplicationRequirementWhereVO=new WebApplicationRequirementWhereVO();
            groupedByGroupId.forEach((k1, v1) -> {
                // 这个是装or的条件
                List<ApplicationRequirementFactoryVO> orList = new ArrayList<>();
                v1.forEach(applicationRequirement -> {
                    ApplicationRequirementFactoryVO applicationRequirementFactoryVO = applicationRequirementFactory.getApplicationRequirementFactoryService(applicationRequirement.getType().getCode())
                            .applicationRequirement(userInfo, applicationRequirement, type);
                    if ("AND".equals(applicationRequirement.getCompoundMode())) {
                        andList.add(applicationRequirementFactoryVO);
                    } else {
                        orList.add(applicationRequirementFactoryVO);
                    }
                });
                if (CollUtil.isNotEmpty(orList)) {
                    multiLevelList.add(orList);
                }
            });
            // 一个完整的申请条件,写入result中
            webApplicationRequirementWhereVO.setOrList(multiLevelList);
            webApplicationRequirementWhereVO.setAndList(andList);
            webApplicationRequirementWhereVO.setSatisfy(webApplicationRequirementWhereVO.whetherMeetTheRequirement());
            result.add(webApplicationRequirementWhereVO);
        });
        WebApplicationRequirementVO webApplicationRequirementVO = new WebApplicationRequirementVO();
        webApplicationRequirementVO.setResult(result);
        return webApplicationRequirementVO;
    }

}
